﻿/* Open source distributed without warranties of any kind. */

namespace Transcriber.Plugins
{
    #region Using
    using System;
    using System.Windows.Forms;
    #endregion

    /// <summary>
    /// Dialog used to convert numbers from one base to another.
    /// </summary>
    public partial class frmNumericBaseConverter : Form
    {
        /// <summary>
        /// Initializes a new instance of the <see cref="frmNumericBaseConverter"/> class.
        /// </summary>
        public frmNumericBaseConverter()
        {
            InitializeComponent();
        }

        private void txtFrom_TextChanged(object sender, EventArgs e)
        {
            this.Convert();
        }

        private void Convert()
        {
            try
            {
                long d = this.Parse(this.txtFrom.Text, (long)this.numFromRadix.Value);
                this.txtTo.Text = this.Format(d, (long)this.numToRadix.Value);
            }
            catch (Exception x)
            {
                MessageBox.Show(x.Message, "Error");
            }
        }

        private string Format(long d, long radix)
        {
            if (d < 0)
            {
                return "-" + this.Format(-d, radix);
            }
            else if (d < radix)
            {
                return this.FormatDigit(d);
            }
            else
            {
                return this.Format(d / radix, radix) + this.FormatDigit(d % radix);
            }
        }

        private string FormatDigit(long d)
        {
            if (d < 10)
            {
                return d.ToString();
            }
            else
            {
                char c = (char)('A' + (d - 10L));
                return new String(c, 1);
            }
        }

        private long Parse(string s, long radix)
        {
            if ((s.Length > 0) && (s[0] == '-'))
            {
                return -(this.Parse(s.Substring(1), radix));
            }

            long result = 0;

            foreach (Char c in s)
            {
                result = (result * radix) + this.ParseDigit(c, radix);
            }

            return result;
        }

        private long ParseDigit(char c, long radix)
        {
            long result;

            if (Char.IsDigit(c))
            {
                result = c - '0';
            }
            else if (Char.IsLetter(c))
            {
                long n = Char.ToUpper(c) - 'A';
                result = n + 10;
            }
            else
            {
                throw new FormatException("Invalid digit " + c.ToString());
            }

            if (result >= radix)
            {
                throw new FormatException("Invalid digit " + c.ToString() + " for radix " + radix);
            }

            return result;
        }

        private void numFromRadix_ValueChanged(object sender, EventArgs e)
        {
            this.Convert();
        }

        private void numToRadix_ValueChanged(object sender, EventArgs e)
        {
            this.Convert();
        }

        private void btnCopy_Click(object sender, EventArgs e)
        {
            Clipboard.SetText(this.txtTo.Text);
        }
    }
}
